home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / MOR55SRC.ZIP / MORIA / SOURCE / STORE2.C < prev    next >
C/C++ Source or Header  |  1992-12-07  |  29KB  |  1,162 lines

  1. /* source/store2.c: store code, entering, command interpreter, buying, selling
  2.  
  3.    Copyright (c) 1989-92 James E. Wilson, Robert A. Koeneke
  4.  
  5.    This software may be copied and distributed for educational, research, and
  6.    not for profit purposes provided that this copyright and statement are
  7.    included in all such copies. */
  8.  
  9. #ifdef __TURBOC__
  10. #include    <stdio.h>
  11. #include    <stdlib.h>
  12. #endif /* __TURBOC__ */
  13.  
  14. #include "config.h"
  15. #include "constant.h"
  16. #include "types.h"
  17. #include "externs.h"
  18.  
  19. #ifdef USG
  20. #ifndef ATARIST_MWC
  21. #include <string.h>
  22. #endif
  23. #else
  24. #include <strings.h>
  25. #endif
  26.  
  27. #if defined(LINT_ARGS)
  28. static void prt_comment1(void);
  29. static void prt_comment2(int32, int32, int);
  30. static void prt_comment3(int32, int32, int);
  31. static void prt_comment4(void);
  32. static void prt_comment5(void);
  33. static void prt_comment6(void);
  34. static void display_commands(void);
  35. static void haggle_commands(int);
  36. static void display_inventory(int, int);
  37. static void display_cost(int, int);
  38. static void store_prt_gold(void);
  39. static void display_store(int, int);
  40. static int get_store_item(int *, char *, int, int);
  41. static int increase_insults(int);
  42. static void decrease_insults(int);
  43. static int haggle_insults(int);
  44. static int get_haggle(char *, int32 *, int);
  45. static int receive_offer(int, char *, int32 *, int32, int, int);
  46. static int purchase_haggle(int, int32 *, struct inven_type *);
  47. static int sell_haggle(int, int32 *, struct inven_type *);
  48. static int store_purchase(int, int *);
  49. static int store_sell(int, int *);
  50. #endif
  51.  
  52. #ifdef ATARIST_TC
  53. /* Include this to get prototypes for standard library functions.  */
  54. #include <stdlib.h>
  55. #endif
  56.  
  57. long atol();
  58.  
  59. static char *comment1[14] = {
  60.   "Done!",  "Accepted!",  "Fine.",  "Agreed!",  "Ok.",  "Taken!",
  61.   "You drive a hard bargain, but taken.",
  62.   "You'll force me bankrupt, but it's a deal.",  "Sigh.  I'll take it.",
  63.   "My poor sick children may starve, but done!",  "Finally!  I accept.",
  64.   "Robbed again.",  "A pleasure to do business with you!",
  65.   "My spouse will skin me, but accepted."
  66.   };
  67.  
  68. static char *comment2a[3] = {
  69.   "%A2 is my final offer; take it or leave it.",
  70.   "I'll give you no more than %A2.",
  71.   "My patience grows thin.  %A2 is final."
  72.   };
  73.  
  74. static char *comment2b[16] = {
  75.   "%A1 for such a fine item?  HA!  No less than %A2.",
  76.   "%A1 is an insult!  Try %A2 gold pieces.",
  77.   "%A1?!?  You would rob my poor starving children?",
  78.   "Why, I'll take no less than %A2 gold pieces.",
  79.   "Ha!  No less than %A2 gold pieces.",
  80.   "Thou knave!  No less than %A2 gold pieces.",
  81.   "%A1 is far too little, how about %A2?",
  82.   "I paid more than %A1 for it myself, try %A2.",
  83.   "%A1?  Are you mad?!?  How about %A2 gold pieces?",
  84.   "As scrap this would bring %A1.  Try %A2 in gold.",
  85.   "May the fleas of 1000 orcs molest you.  I want %A2.",
  86.   "My mother you can get for %A1, this costs %A2.",
  87.   "May your chickens grow lips.  I want %A2 in gold!",
  88.   "Sell this for such a pittance?  Give me %A2 gold.",
  89.   "May the Balrog find you tasty!  %A2 gold pieces?",
  90.   "Your mother was a Troll!  %A2 or I'll tell."
  91.   };
  92.  
  93. static char *comment3a[3] = {
  94.   "I'll pay no more than %A1; take it or leave it.",
  95.   "You'll get no more than %A1 from me.",
  96.   "%A1 and that's final."
  97.   };
  98.  
  99. static char *comment3b[15] = {
  100.   "%A2 for that piece of junk?  No more than %A1.",
  101.   "For %A2 I could own ten of those.  Try %A1.",
  102.   "%A2?  NEVER!  %A1 is more like it.",
  103.   "Let's be reasonable. How about %A1 gold pieces?",
  104.   "%A1 gold for that junk, no more.",
  105.   "%A1 gold pieces and be thankful for it!",
  106.   "%A1 gold pieces and not a copper more.",
  107.   "%A2 gold?  HA!  %A1 is more like it.",  "Try about %A1 gold.",
  108.   "I wouldn't pay %A2 for your children, try %A1.",
  109.   "*CHOKE* For that!?  Let's say %A1.",  "How about %A1?",
  110.   "That looks war surplus!  Say %A1 gold.",
  111.   "I'll buy it as scrap for %A1.",
  112.   "%A2 is too much, let us say %A1 gold."
  113.   };
  114.  
  115. static char *comment4a[5] = {
  116.   "ENOUGH!  You have abused me once too often!",
  117.   "THAT DOES IT!  You shall waste my time no more!",
  118.   "This is getting nowhere.  I'm going home!",
  119.   "BAH!  No more shall you insult me!",
  120.   "Begone!  I have had enough abuse for one day."
  121.   };
  122.  
  123. static char *comment4b[5] = {
  124.   "Out of my place!",  "out... Out... OUT!!!",  "Come back tomorrow.",
  125.   "Leave my place.  Begone!",  "Come back when thou art richer."
  126.   };
  127.  
  128. static char *comment5[10] = {
  129.   "You will have to do better than that!",  "That's an insult!",
  130.   "Do you wish to do business or not?",  "Hah!  Try again.",
  131.   "Ridiculous!",  "You've got to be kidding!",  "You'd better be kidding!",
  132.   "You try my patience.",  "I don't hear you.",
  133.   "Hmmm, nice weather we're having."
  134.   };
  135.  
  136. static char *comment6[5] = {
  137.   "I must have heard you wrong.",  "What was that?",
  138.   "I'm sorry, say that again.",  "What did you say?",
  139.   "Sorry, what was that again?"
  140.   };
  141.  
  142.  
  143. extern int16 last_store_inc;
  144.  
  145. /* Comments vary.                    -RAK-    */
  146. /* Comment one : Finished haggling                */
  147. static void prt_comment1()
  148. {
  149.   msg_print(comment1[randint(14)-1]);
  150. }
  151.  
  152.  
  153. /* %A1 is offer, %A2 is asking.        */
  154. static void prt_comment2(offer, asking, final)
  155. int32 offer, asking; int final;
  156. {
  157.   vtype comment;
  158.  
  159.   if (final > 0)
  160.     (void) strcpy(comment, comment2a[randint(3)-1]);
  161.   else
  162.     (void) strcpy(comment, comment2b[randint(16)-1]);
  163.  
  164.   insert_lnum(comment, "%A1", offer, FALSE);
  165.   insert_lnum(comment, "%A2", asking, FALSE);
  166.   msg_print(comment);
  167. }
  168.  
  169.  
  170. static void prt_comment3(offer, asking, final)
  171. int32 offer, asking; int final;
  172. {
  173.   vtype comment;
  174.  
  175.   if (final > 0)
  176.     (void) strcpy (comment, comment3a[randint(3)-1]);
  177.   else
  178.     (void) strcpy (comment, comment3b[randint(15)-1]);
  179.  
  180.   insert_lnum(comment, "%A1", offer, FALSE);
  181.   insert_lnum(comment, "%A2", asking, FALSE);
  182.   msg_print(comment);
  183. }
  184.  
  185.  
  186. /* Kick 'da bum out.                    -RAK-    */
  187. static void prt_comment4()
  188. {
  189.   register int tmp;
  190.  
  191.   tmp = randint(5) - 1;
  192.   msg_print(comment4a[tmp]);
  193.   msg_print(comment4b[tmp]);
  194. }
  195.  
  196.  
  197. static void prt_comment5()
  198. {
  199.   msg_print(comment5[randint(10)-1]);
  200. }
  201.  
  202.  
  203. static void prt_comment6()
  204. {
  205.   msg_print (comment6[randint(5)-1]);
  206. }
  207.  
  208.  
  209. /* Displays the set of commands                -RAK-    */
  210. static void display_commands()
  211. {
  212.   prt("You may:", 20, 0);
  213.   prt(" p) Purchase an item.           b) Browse store's inventory.", 21, 0);
  214.   prt(" s) Sell an item.               i/e/t/w/x) Inventory/Equipment Lists.",
  215.       22, 0);
  216.   prt("ESC) Exit from Building.        ^R) Redraw the screen.", 23, 0);
  217. }
  218.  
  219.  
  220. /* Displays the set of commands                -RAK-    */
  221. static void haggle_commands(typ)
  222. int typ;
  223. {
  224.   if (typ == -1)
  225.     prt("Specify an asking-price in gold pieces.", 21, 0);
  226.   else
  227.     prt("Specify an offer in gold pieces.", 21, 0);
  228.   prt("ESC) Quit Haggling.", 22, 0);
  229.   erase_line (23, 0);    /* clear last line */
  230. }
  231.  
  232.  
  233. /* Displays a store's inventory                -RAK-    */
  234. static void display_inventory(store_num, start)
  235. int store_num, start;
  236. {
  237.   register store_type *s_ptr;
  238.   register inven_type *i_ptr;
  239.   register int i, j, stop;
  240.   bigvtype out_val1, out_val2;
  241.   int32 x;
  242.  
  243.   s_ptr = &store[store_num];
  244.   i = (start % 12);
  245.   stop = ((start / 12) + 1) * 12;
  246.   if (stop > s_ptr->store_ctr)    stop = s_ptr->store_ctr;
  247.   while (start < stop)
  248.     {
  249.       i_ptr = &s_ptr->store_inven[start].sitem;
  250.       x = i_ptr->number;
  251.       if ((i_ptr->subval >= ITEM_SINGLE_STACK_MIN)
  252.       && (i_ptr->subval <= ITEM_SINGLE_STACK_MAX))
  253.     i_ptr->number = 1;
  254.       objdes(out_val1, i_ptr, TRUE);
  255.       i_ptr->number = x;
  256.       (void) sprintf(out_val2, "%c) %s", 'a'+i, out_val1);
  257.       prt(out_val2, i+5, 0);
  258.       x = s_ptr->store_inven[start].scost;
  259.       if (x <= 0)
  260.     {
  261.       int32 value = -x;
  262.       value = value * chr_adj() / 100;
  263.       if (value <= 0)
  264.         value = 1;
  265.       (void) sprintf(out_val2, "%9ld", value);
  266.     }
  267.       else
  268.     (void) sprintf(out_val2,"%9ld [Fixed]", x);
  269.       prt(out_val2, i+5, 59);
  270.       i++;
  271.       start++;
  272.     }
  273.   if (i < 12)
  274.     for (j = 0; j < (11 - i + 1); j++)
  275.       erase_line (j+i+5, 0); /* clear remaining lines */
  276.   if (s_ptr->store_ctr > 12)
  277.     put_buffer("- cont. -", 17, 60);
  278.   else
  279.     erase_line (17, 60);
  280. }
  281.  
  282.  
  283. /* Re-displays only a single cost            -RAK-    */
  284. static void display_cost(store_num, pos)
  285. int store_num, pos;
  286. {
  287.   register int i;
  288.   register int32 j;
  289.   vtype out_val;
  290.   register store_type *s_ptr;
  291.  
  292.   s_ptr = &store[store_num];
  293.   i = (pos % 12);
  294.   if (s_ptr->store_inven[pos].scost < 0)
  295.     {
  296.       j = - s_ptr->store_inven[pos].scost;
  297.       j = j * chr_adj() / 100;
  298.       (void) sprintf(out_val, "%ld", j);
  299.     }
  300.   else
  301.     (void) sprintf(out_val, "%9ld [Fixed]", s_ptr->store_inven[pos].scost);
  302.   prt(out_val, i+5, 59);
  303. }
  304.  
  305.  
  306. /* Displays players gold                    -RAK-    */
  307. static void store_prt_gold()
  308. {
  309.   vtype out_val;
  310.  
  311.   (void) sprintf(out_val, "Gold Remaining : %ld", py.misc.au);
  312.   prt(out_val, 18, 17);
  313. }
  314.  
  315.  
  316. /* Displays store                    -RAK-    */
  317. static void display_store(store_num, cur_top)
  318. int store_num, cur_top;
  319. {
  320.   register store_type *s_ptr;
  321.  
  322.   s_ptr = &store[store_num];
  323.   clear_screen();
  324.   put_buffer(owners[s_ptr->owner].owner_name, 3, 9);
  325.   put_buffer("Item", 4, 3);
  326.   put_buffer("Asking Price", 4, 60);
  327.   store_prt_gold();
  328.   display_commands();
  329.   display_inventory(store_num, cur_top);
  330. }
  331.  
  332.  
  333. /* Get the ID of a store item and return it's value    -RAK-    */
  334. static int get_store_item(com_val, pmt, i, j)
  335. int *com_val;
  336. char *pmt;
  337. register int i, j;
  338. {
  339.   char command;
  340.   vtype out_val;
  341.   register int flag;
  342.  
  343.   *com_val = -1;
  344.   flag = FALSE;
  345.   (void) sprintf(out_val, "(Items %c-%c, ESC to exit) %s", i+'a', j+'a', pmt);
  346.   while (get_com(out_val, &command))
  347.     {
  348.       command -= 'a';
  349.       if (command >= i && command <= j)
  350.     {
  351.       flag = TRUE;
  352.       *com_val = command;
  353.       break;
  354.     }
  355.       bell();
  356.     }
  357.   erase_line(MSG_LINE, 0);
  358.   return(flag);
  359. }
  360.  
  361.  
  362. /* Increase the insult counter and get angry if too many -RAK-    */
  363. static int increase_insults(store_num)
  364. int store_num;
  365. {
  366.   register int increase;
  367.   register store_type *s_ptr;
  368.  
  369.   increase = FALSE;
  370.   s_ptr = &store[store_num];
  371.   s_ptr->insult_cur++;
  372.   if (s_ptr->insult_cur > owners[s_ptr->owner].insult_max)
  373.     {
  374.       prt_comment4();
  375.       s_ptr->insult_cur = 0;
  376.       s_ptr->good_buy = 0;
  377.       s_ptr->bad_buy = 0;
  378.       s_ptr->store_open = turn + 2500 + randint(2500);
  379.       increase = TRUE;
  380.     }
  381.   return(increase);
  382. }
  383.  
  384.  
  385. /* Decrease insults                    -RAK-    */
  386. static void decrease_insults(store_num)
  387. int store_num;
  388. {
  389.   register store_type *s_ptr;
  390.  
  391.   s_ptr = &store[store_num];
  392.   if (s_ptr->insult_cur != 0)
  393.     s_ptr->insult_cur--;
  394. }
  395.  
  396.  
  397. /* Have insulted while haggling                -RAK-    */
  398. static int haggle_insults(store_num)
  399. int store_num;
  400. {
  401.   register int haggle;
  402.  
  403.   haggle = FALSE;
  404.   if (increase_insults(store_num))
  405.     haggle = TRUE;
  406.   else
  407.     {
  408.       prt_comment5();
  409.       msg_print (CNIL); /* keep insult separate from rest of haggle */
  410.     }
  411.   return(haggle);
  412. }
  413.  
  414.  
  415. static int get_haggle(comment, new_offer, num_offer)
  416. char *comment;
  417. int32 *new_offer;
  418. int num_offer;
  419. {
  420.   register int32 i;
  421.   vtype out_val, default_offer;
  422.   register int flag, clen;
  423.   int orig_clen;
  424.   register char *p;
  425.   int increment;
  426.  
  427.   flag = TRUE;
  428.   increment = FALSE;
  429.   clen = strlen(comment);
  430.   orig_clen = clen;
  431.   if (num_offer == 0)
  432.     last_store_inc = 0;
  433.   i = 0;
  434.   do
  435.     {
  436.       prt(comment, 0, 0);
  437.       if (num_offer && last_store_inc != 0)
  438.     {
  439.       (void) sprintf (default_offer, "[%c%d] ",
  440.               (last_store_inc < 0) ? '-' : '+',
  441.               abs (last_store_inc));
  442.       prt (default_offer, 0, orig_clen);
  443.       clen = orig_clen + strlen (default_offer);
  444.     }
  445.       if (!get_string(out_val, 0, clen, 40))
  446.     flag = FALSE;
  447.       for (p = out_val; *p == ' '; p++)
  448.     ;
  449.       if (*p == '+' || *p == '-')
  450.     increment = TRUE;
  451.       if (num_offer && increment)
  452.     {
  453.       i = atol (out_val);
  454.       /* Don't accept a zero here.  Turn off increment if it was zero
  455.          because a zero will not exit.  This can be zero if the user
  456.          did not type a number after the +/- sign.  */
  457.       if (i == 0)
  458.         increment = FALSE;
  459.       else
  460.         last_store_inc = i;
  461.     }
  462.       else if (num_offer && *out_val == '\0')
  463.     {
  464.       i = last_store_inc;
  465.       increment = TRUE;
  466.     }
  467.       else
  468.     i = atol (out_val);
  469.  
  470.       /* don't allow incremental haggling, if player has not made an offer
  471.      yet */
  472.       if (flag && num_offer == 0 && increment)
  473.     {
  474.       msg_print("You haven't even made your first offer yet!");
  475.       i = 0;
  476.       increment = FALSE;
  477.     }
  478.     }
  479.   while (flag && (i == 0));
  480.   if (flag)
  481.     {
  482.       if (increment)
  483.     *new_offer += i;
  484.       else
  485.     *new_offer = i;
  486.     }
  487.   else
  488.     erase_line (0, 0);
  489.   return(flag);
  490. }
  491.  
  492.  
  493. static int receive_offer(store_num, comment, new_offer, last_offer,
  494.              num_offer, factor)
  495. int store_num;
  496. char *comment;
  497. register int32 *new_offer, last_offer;
  498. int num_offer, factor;
  499. {
  500.   register int flag;
  501.   register int receive;
  502.  
  503.   receive = 0;
  504.   flag = FALSE;
  505.   do
  506.     {
  507.       if (get_haggle(comment, new_offer, num_offer))
  508.     {
  509.       if (*new_offer*factor >= last_offer*factor)
  510.         flag = TRUE;
  511.       else if (haggle_insults(store_num))
  512.         {
  513.           receive = 2;
  514.           flag = TRUE;
  515.         }
  516.       else
  517.         /* new_offer rejected, reset new_offer so that incremental
  518.            haggling works correctly */
  519.         *new_offer = last_offer;
  520.     }
  521.       else
  522.     {
  523.       receive = 1;
  524.       flag = TRUE;
  525.     }
  526.     }
  527.   while (!flag);
  528.   return(receive);
  529. }
  530.  
  531.  
  532. /* Haggling routine                    -RAK-    */
  533. static int purchase_haggle(store_num, price, item)
  534. int store_num;
  535. int32 *price;
  536. inven_type *item;
  537. {
  538.   int32 max_sell, min_sell, max_buy;
  539.   int32 cost, cur_ask, final_ask, min_offer;
  540.   int32 last_offer, new_offer;
  541.   int32 x1, x2, x3;
  542.   int32 min_per, max_per;
  543.   register int flag, loop_flag;
  544.   char *comment;
  545.   vtype out_val;
  546.   int purchase, num_offer, final_flag, didnt_haggle;
  547.   register store_type *s_ptr;
  548.   register owner_type *o_ptr;
  549.  
  550.   flag = FALSE;
  551.   purchase = 0;
  552.   *price = 0;
  553.   final_flag = 0;
  554.   didnt_haggle = FALSE;
  555.   s_ptr = &store[store_num];
  556.   o_ptr = &owners[s_ptr->owner];
  557.   cost = sell_price(store_num, &max_sell, &min_sell, item);
  558.   max_sell = max_sell * chr_adj() / 100;
  559.   if (max_sell <= 0)  max_sell = 1;
  560.   min_sell = min_sell * chr_adj() / 100;
  561.   if (min_sell <= 0)  min_sell = 1;
  562.   /* cast max_inflate to signed so that subtraction works correctly */
  563.   max_buy  = cost * (200 - (int)o_ptr->max_inflate) / 100;
  564.   if (max_buy <= 0) max_buy = 1;
  565.   min_per  = o_ptr->haggle_per;
  566.   max_per  = min_per * 3;
  567.   haggle_commands(1);
  568.   cur_ask   = max_sell;
  569.   final_ask = min_sell;
  570.   min_offer = max_buy;
  571.   last_offer = min_offer;
  572.   new_offer = 0;
  573.   num_offer = 0; /* this prevents incremental haggling on first try */
  574.   comment = "Asking";
  575.  
  576.   /* go right to final price if player has bargained well */
  577.   if (noneedtobargain(store_num, final_ask))
  578.     {
  579.       msg_print("After a long bargaining session, you agree upon the price.");
  580.       cur_ask = min_sell;
  581.       comment = "Final offer";
  582.       didnt_haggle = TRUE;
  583.  
  584.       /* Set up automatic increment, so that a return will accept the
  585.      final price.  */
  586.       last_store_inc = min_sell;
  587.       num_offer = 1;
  588.     }
  589.  
  590.   do
  591.     {
  592.       do
  593.     {
  594.       loop_flag = TRUE;
  595.       (void) sprintf(out_val, "%s :  %ld", comment, cur_ask);
  596.       put_buffer(out_val, 1, 0);
  597.       purchase = receive_offer(store_num, "What do you offer? ",
  598.                    &new_offer, last_offer, num_offer, 1);
  599.       if (purchase != 0)
  600.         flag = TRUE;
  601.       else
  602.         {
  603.           if (new_offer > cur_ask)
  604.         {
  605.           prt_comment6();
  606.           /* rejected, reset new_offer for incremental haggling */
  607.           new_offer = last_offer;
  608.  
  609.           /* If the automatic increment is large enough to overflow,
  610.              then the player must have made a mistake.  Clear it
  611.              because it is useless.  */
  612.           if (last_offer + last_store_inc > cur_ask)
  613.             last_store_inc = 0;
  614.         }
  615.           else if (new_offer == cur_ask)
  616.         {
  617.           flag = TRUE;
  618.           *price = new_offer;
  619.         }
  620.           else
  621.         loop_flag = FALSE;
  622.         }
  623.     }
  624.       while (!flag && loop_flag);
  625.       if (!flag)
  626.     {
  627.       x1 = (new_offer - last_offer) * 100 / (cur_ask - last_offer);
  628.       if (x1 < min_per)
  629.         {
  630.           flag = haggle_insults(store_num);
  631.           if (flag)     purchase = 2;
  632.         }
  633.       else if (x1 > max_per)
  634.         {
  635.           x1 = x1 * 75 / 100;
  636.           if (x1 < max_per)     x1 = max_per;
  637.         }
  638.       x2 = x1 + randint(5) - 3;
  639.       x3 = ((cur_ask - new_offer) * x2 / 100) + 1;
  640.       /* don't let the price go up */
  641.       if (x3 < 0)
  642.         x3 = 0;
  643.       cur_ask -= x3;
  644.       if (cur_ask < final_ask)
  645.         {
  646.           cur_ask = final_ask;
  647.           comment = "Final Offer";
  648.           /* Set the automatic haggle increment so that RET will give
  649.          a new_offer equal to the final_ask price.  */
  650.           last_store_inc = final_ask - new_offer;
  651.           final_flag++;
  652.           if (final_flag > 3)
  653.         {
  654.           if (increase_insults(store_num))
  655.             purchase = 2;
  656.           else
  657.             purchase = 1;
  658.           flag = TRUE;
  659.         }
  660.         }
  661.       else if (new_offer >= cur_ask)
  662.         {
  663.           flag = TRUE;
  664.           *price = new_offer;
  665.         }
  666.       if (!flag)
  667.         {
  668.           last_offer = new_offer;
  669.           num_offer++; /* enable incremental haggling */
  670.           erase_line (1, 0);
  671.           (void) sprintf(out_val, "Your last offer : %ld", last_offer);
  672.           put_buffer(out_val, 1, 39);
  673.           prt_comment2(last_offer, cur_ask, final_flag);
  674.  
  675.           /* If the current increment would take you over the store's
  676.          price, then decrease it to an exact match.  */
  677.           if (cur_ask - last_offer < last_store_inc)
  678.         last_store_inc = cur_ask - last_offer;
  679.         }
  680.     }
  681.     }
  682.   while (!flag);
  683.  
  684.   /* update bargaining info */
  685.   if ((purchase == 0) && (!didnt_haggle))
  686.     updatebargain(store_num, *price, final_ask);
  687.  
  688.   return(purchase);
  689. }
  690.  
  691.  
  692. /* Haggling routine                    -RAK-    */
  693. static int sell_haggle(store_num, price, item)
  694. int store_num;
  695. int32 *price;
  696. inven_type *item;
  697. {
  698.   int32 max_sell, max_buy, min_buy;
  699.   int32 cost, cur_ask, final_ask, min_offer;
  700.   int32 last_offer, new_offer;
  701.   int32 max_gold;
  702.   int32 x1, x2, x3;
  703.   int32 min_per, max_per;
  704.   register int flag, loop_flag;
  705.   char *comment;
  706.   vtype out_val;
  707.   register store_type *s_ptr;
  708.   register owner_type *o_ptr;
  709.   int sell, num_offer, final_flag, didnt_haggle;
  710.  
  711.   flag = FALSE;
  712.   sell = 0;
  713.   *price = 0;
  714.   final_flag = 0;
  715.   didnt_haggle = FALSE;
  716.   s_ptr = &store[store_num];
  717.   cost = item_value(item);
  718.   if (cost < 1)
  719.     {
  720.       sell = 3;
  721.       flag = TRUE;
  722.     }
  723.   else
  724.     {
  725.       o_ptr = &owners[s_ptr->owner];
  726.       cost = cost * (200 - chr_adj()) / 100;
  727.       cost = cost * (200 - rgold_adj[o_ptr->owner_race][py.misc.prace]) / 100;
  728.       if (cost < 1)  cost = 1;
  729.       max_sell = cost * o_ptr->max_inflate / 100;
  730.       /* cast max_inflate to signed so that subtraction works correctly */
  731.       max_buy  = cost * (200 - (int)o_ptr->max_inflate) / 100;
  732.       min_buy  = cost * (200 - o_ptr->min_inflate) / 100;
  733.       if (min_buy < 1) min_buy = 1;
  734.       if (max_buy < 1) max_buy = 1;
  735.       if (min_buy < max_buy)  min_buy = max_buy;
  736.       min_per  = o_ptr->haggle_per;
  737.       max_per  = min_per * 3;
  738.       max_gold = o_ptr->max_cost;
  739.     }
  740.   if (!flag)
  741.     {
  742.       haggle_commands(-1);
  743.       num_offer = 0; /* this prevents incremental haggling on first try */
  744.       if (max_buy > max_gold)
  745.     {
  746.       final_flag= 1;
  747.       comment = "Final Offer";
  748.       /* Disable the automatic haggle increment on RET.  */
  749.       last_store_inc = 0;
  750.       cur_ask   = max_gold;
  751.       final_ask = max_gold;
  752.       msg_print("I am sorry, but I have not the money to afford such \
  753. a fine item.");
  754.       didnt_haggle = TRUE;
  755.     }
  756.       else
  757.     {
  758.       cur_ask   = max_buy;
  759.       final_ask = min_buy;
  760.       if (final_ask > max_gold)
  761.         final_ask = max_gold;
  762.       comment = "Offer";
  763.  
  764.       /* go right to final price if player has bargained well */
  765.           if (noneedtobargain(store_num, final_ask))
  766.         {
  767.           msg_print("After a long bargaining session, you agree upon \
  768. the price.");
  769.               cur_ask = final_ask;
  770.           comment = "Final offer";
  771.           didnt_haggle = TRUE;
  772.  
  773.           /* Set up automatic increment, so that a return will accept the
  774.          final price.  */
  775.           last_store_inc = final_ask;
  776.           num_offer = 1;
  777.             }
  778.     }
  779.       min_offer = max_sell;
  780.       last_offer = min_offer;
  781.       new_offer = 0;
  782.       if (cur_ask < 1)    cur_ask = 1;
  783.       do
  784.     {
  785.       do
  786.         {
  787.           loop_flag = TRUE;
  788.           (void) sprintf(out_val, "%s :  %ld", comment, cur_ask);
  789.           put_buffer(out_val, 1, 0);
  790.           sell = receive_offer(store_num, "What price do you ask? ",
  791.                  &new_offer, last_offer, num_offer, -1);
  792.           if (sell != 0)
  793.         flag   = TRUE;
  794.           else
  795.         {
  796.           if (new_offer < cur_ask)
  797.             {
  798.               prt_comment6();
  799.               /* rejected, reset new_offer for incremental haggling */
  800.               new_offer = last_offer;
  801.  
  802.               /* If the automatic increment is large enough to
  803.              overflow, then the player must have made a mistake.
  804.              Clear it because it is useless.  */
  805.               if (last_offer + last_store_inc < cur_ask)
  806.             last_store_inc = 0;
  807.             }
  808.           else if (new_offer == cur_ask)
  809.             {
  810.               flag = TRUE;
  811.               *price = new_offer;
  812.             }
  813.           else
  814.             loop_flag = FALSE;
  815.         }
  816.         }
  817.       while (!flag && loop_flag);
  818.       if (!flag)
  819.         {
  820.           x1 = (last_offer - new_offer) * 100 / (last_offer - cur_ask);
  821.           if (x1 < min_per)
  822.         {
  823.           flag = haggle_insults(store_num);
  824.           if (flag)  sell = 2;
  825.         }
  826.           else if (x1 > max_per)
  827.         {
  828.           x1 = x1 * 75 / 100;
  829.           if (x1 < max_per)  x1 = max_per;
  830.         }
  831.           x2 = x1 + randint(5) - 3;
  832.           x3 = ((new_offer - cur_ask) * x2 / 100) + 1;
  833.           /* don't let the price go down */
  834.           if (x3 < 0)
  835.         x3 = 0;
  836.           cur_ask += x3;
  837.           if (cur_ask > final_ask)
  838.         {
  839.           cur_ask = final_ask;
  840.           comment = "Final Offer";
  841.           /* Set the automatic haggle increment so that RET will give
  842.              a new_offer equal to the final_ask price.  */
  843.           last_store_inc = final_ask - new_offer;
  844.           final_flag++;
  845.           if (final_flag > 3)
  846.             {
  847.               if (increase_insults(store_num))
  848.             sell = 2;
  849.               else
  850.             sell = 1;
  851.               flag = TRUE;
  852.             }
  853.         }
  854.           else if (new_offer <= cur_ask)
  855.         {
  856.           flag = TRUE;
  857.           *price = new_offer;
  858.         }
  859.           if (!flag)
  860.         {
  861.           last_offer = new_offer;
  862.           num_offer++; /* enable incremental haggling */
  863.           erase_line (1, 0);
  864.           (void) sprintf(out_val, "Your last bid %ld", last_offer);
  865.           put_buffer(out_val, 1, 39);
  866.           prt_comment3(cur_ask, last_offer, final_flag);
  867.  
  868.           /* If the current decrement would take you under the store's
  869.              price, then increase it to an exact match.  */
  870.           if (cur_ask - last_offer > last_store_inc)
  871.             last_store_inc = cur_ask - last_offer;
  872.         }
  873.         }
  874.     }
  875.       while (!flag);
  876.     }
  877.  
  878.   /* update bargaining info */
  879.   if ((sell == 0) && (!didnt_haggle))
  880.     updatebargain(store_num, *price, final_ask);
  881.  
  882.   return(sell);
  883. }
  884.  
  885.  
  886. /* Buy an item from a store                -RAK-    */
  887. static int store_purchase(store_num, cur_top)
  888. int store_num;
  889. int *cur_top;
  890. {
  891.   int32 price;
  892.   register int i, choice;
  893.   bigvtype out_val, tmp_str;
  894.   register store_type *s_ptr;
  895.   inven_type sell_obj;
  896.   register inven_record *r_ptr;
  897.   int item_val, item_new, purchase;
  898.  
  899.   purchase = FALSE;
  900.   s_ptr = &store[store_num];
  901.   /* i == number of objects shown on screen    */
  902.   if (*cur_top == 12)
  903.     i = s_ptr->store_ctr - 1 - 12;
  904.   else if (s_ptr->store_ctr > 11)
  905.     i = 11;
  906.   else
  907.     i = s_ptr->store_ctr - 1;
  908.   if (s_ptr->store_ctr < 1)
  909.     msg_print("I am currently out of stock.");
  910.       /* Get the item number to be bought        */
  911.   else if (get_store_item(&item_val,
  912.               "Which item are you interested in? ", 0, i))
  913.     {
  914.       item_val = item_val + *cur_top;    /* TRUE item_val    */
  915.       take_one_item(&sell_obj, &s_ptr->store_inven[item_val].sitem);
  916.       if (inven_check_num(&sell_obj))
  917.     {
  918.       if (s_ptr->store_inven[item_val].scost > 0)
  919.         {
  920.           price = s_ptr->store_inven[item_val].scost;
  921.           choice = 0;
  922.         }
  923.       else
  924.         choice = purchase_haggle(store_num, &price, &sell_obj);
  925.       if (choice == 0)
  926.         {
  927.           if (py.misc.au >= price)
  928.         {
  929.           prt_comment1();
  930.           decrease_insults(store_num);
  931.           py.misc.au -= price;
  932.           item_new = inven_carry(&sell_obj);
  933.           i = s_ptr->store_ctr;
  934.           store_destroy(store_num, item_val, TRUE);
  935.           objdes(tmp_str, &inventory[item_new], TRUE);
  936.           (void) sprintf(out_val, "You have %s (%c)",
  937.                    tmp_str, item_new+'a');
  938.           prt(out_val, 0, 0);
  939.           check_strength();
  940.           if (*cur_top >= s_ptr->store_ctr)
  941.             {
  942.               *cur_top = 0;
  943.               display_inventory(store_num, *cur_top);
  944.             }
  945.           else
  946.             {
  947.               r_ptr = &s_ptr->store_inven[item_val];
  948.               if (i == s_ptr->store_ctr)
  949.             {
  950.               if (r_ptr->scost < 0)
  951.                 {
  952.                   r_ptr->scost = price;
  953.                   display_cost(store_num, item_val);
  954.                 }
  955.             }
  956.               else
  957.             display_inventory(store_num, item_val);
  958.             }
  959.           store_prt_gold();
  960.         }
  961.           else
  962.         {
  963.           if (increase_insults(store_num))
  964.             purchase = TRUE;
  965.           else
  966.             {
  967.               prt_comment1();
  968.               msg_print("Liar!  You have not the gold!");
  969.             }
  970.         }
  971.         }
  972.       else if (choice == 2)
  973.         purchase = TRUE;
  974.  
  975.       /* Less intuitive, but looks better here than in purchase_haggle. */
  976.       display_commands();
  977.       erase_line (1, 0);
  978.     }
  979.       else
  980.     prt("You cannot carry that many different items.", 0, 0);
  981.     }
  982.   return(purchase);
  983. }
  984.  
  985.  
  986. /* Sell an item to the store                -RAK-    */
  987. static int store_sell(store_num, cur_top)
  988. int store_num, *cur_top;
  989. {
  990.   int item_val, item_pos;
  991.   int32 price;
  992.   bigvtype out_val, tmp_str;
  993.   inven_type sold_obj;
  994.   register int sell, choice, flag;
  995.   char mask[INVEN_WIELD];
  996.   int counter, first_item, last_item;
  997.  
  998.   sell = FALSE;
  999.   first_item = inven_ctr;
  1000.   last_item = -1;
  1001.   for (counter = 0; counter < inven_ctr; counter++)
  1002.     {
  1003. #ifdef MAC
  1004.       flag = store_buy(store_num, (inventory[counter].tval));
  1005. #else
  1006.       flag = (*store_buy[store_num])(inventory[counter].tval);
  1007. #endif
  1008.       mask[counter] = flag;
  1009.       if (flag)
  1010.     {
  1011.       if (counter < first_item)
  1012.         first_item = counter;
  1013.       if (counter > last_item)
  1014.         last_item = counter;
  1015.     } /* end of if (flag) */
  1016.     } /* end of for (counter) */
  1017.   if (last_item == -1)
  1018.     msg_print("You have nothing to sell to this store!");
  1019.   else if (get_item(&item_val, "Which one? ", first_item, last_item, mask,
  1020.             "I do not buy such items."))
  1021.     {
  1022.       take_one_item(&sold_obj, &inventory[item_val]);
  1023.       objdes(tmp_str, &sold_obj, TRUE);
  1024.       (void) sprintf(out_val, "Selling %s (%c)", tmp_str, item_val+'a');
  1025.       msg_print(out_val);
  1026.       if (store_check_num(&sold_obj, store_num))
  1027.     {
  1028.       choice = sell_haggle(store_num, &price, &sold_obj);
  1029.       if (choice == 0)
  1030.         {
  1031.           prt_comment1();
  1032.           decrease_insults(store_num);
  1033.           py.misc.au += price;
  1034.           /* identify object in inventory to set object_ident */
  1035.           identify(&item_val);
  1036.           /* retake sold_obj so that it will be identified */
  1037.           take_one_item(&sold_obj, &inventory[item_val]);
  1038.           /* call known2 for store item, so charges/pluses are known */
  1039.           known2(&sold_obj);
  1040.           inven_destroy(item_val);
  1041.           objdes(tmp_str, &sold_obj, TRUE);
  1042.           (void) sprintf(out_val, "You've sold %s", tmp_str);
  1043.           msg_print(out_val);
  1044.           store_carry(store_num, &item_pos, &sold_obj);
  1045.           check_strength();
  1046.           if (item_pos >= 0)
  1047.         {
  1048.           if (item_pos < 12)
  1049.             if (*cur_top < 12)
  1050.               display_inventory(store_num, item_pos);
  1051.             else
  1052.               {
  1053.             *cur_top = 0;
  1054.             display_inventory(store_num, *cur_top);
  1055.               }
  1056.           else if (*cur_top > 11)
  1057.             display_inventory(store_num, item_pos);
  1058.           else
  1059.             {
  1060.               *cur_top = 12;
  1061.               display_inventory(store_num, *cur_top);
  1062.             }
  1063.         }
  1064.           store_prt_gold();
  1065.         }
  1066.       else if (choice == 2)
  1067.         sell = TRUE;
  1068.       else if (choice == 3)
  1069.         {
  1070.           msg_print("How dare you!");
  1071.           msg_print("I will not buy that!");
  1072.           sell = increase_insults(store_num);
  1073.         }
  1074.       /* Less intuitive, but looks better here than in sell_haggle. */
  1075.       erase_line (1, 0);
  1076.       display_commands();
  1077.     }
  1078.       else
  1079.     msg_print("I have not the room in my store to keep it.");
  1080.     }
  1081.   return(sell);
  1082. }
  1083.  
  1084.  
  1085. /* Entering a store                    -RAK-    */
  1086. void enter_store(store_num)
  1087. int store_num;
  1088. {
  1089.   int cur_top, tmp_chr;
  1090.   char command;
  1091.   register int exit_flag;
  1092.   register store_type *s_ptr;
  1093.  
  1094.   s_ptr = &store[store_num];
  1095.   if (s_ptr->store_open < turn)
  1096.     {
  1097.       exit_flag = FALSE;
  1098.       cur_top = 0;
  1099.       display_store(store_num, cur_top);
  1100.       do
  1101.     {
  1102.       move_cursor (20, 9);
  1103.       /* clear the msg flag just like we do in dungeon.c */
  1104.       msg_flag = FALSE;
  1105.       if (get_com(CNIL, &command))
  1106.         {
  1107.           switch(command)
  1108.         {
  1109.         case 'b':
  1110.           if (cur_top == 0)
  1111.             if (s_ptr->store_ctr > 12)
  1112.               {
  1113.             cur_top = 12;
  1114.             display_inventory(store_num, cur_top);
  1115.               }
  1116.             else
  1117.               msg_print("Entire inventory is shown.");
  1118.           else
  1119.             {
  1120.               cur_top = 0;
  1121.               display_inventory(store_num, cur_top);
  1122.             }
  1123.           break;
  1124.         case 'E': case 'e':     /* Equipment List    */
  1125.         case 'I': case 'i':     /* Inventory        */
  1126.         case 'T': case 't':     /* Take off        */
  1127.         case 'W': case 'w':    /* Wear            */
  1128.         case 'X': case 'x':    /* Switch weapon        */
  1129.           tmp_chr = py.stats.use_stat[A_CHR];
  1130.           do
  1131.             {
  1132.               inven_command(command);
  1133.               command = doing_inven;
  1134.             }
  1135.           while (command);
  1136.           /* redisplay store prices if charisma changes */
  1137.           if (tmp_chr != py.stats.use_stat[A_CHR])
  1138.             display_inventory(store_num, cur_top);
  1139.           free_turn_flag = FALSE;    /* No free moves here. -CJS- */
  1140.           break;
  1141.         case 'p':
  1142.           exit_flag = store_purchase(store_num, &cur_top);
  1143.           break;
  1144.         case 's':
  1145.           exit_flag = store_sell(store_num, &cur_top);
  1146.           break;
  1147.         default:
  1148.           bell();
  1149.           break;
  1150.         }
  1151.         }
  1152.       else
  1153.         exit_flag = TRUE;
  1154.     }
  1155.       while (!exit_flag);
  1156.       /* Can't save and restore the screen because inven_command does that. */
  1157.       draw_cave();
  1158.     }
  1159.   else
  1160.     msg_print("The doors are locked.");
  1161. }
  1162.